package com.atguigu.gmall.order.receiver;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.client.PaymentFeignClient;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.payment.PaymentInfo;
import com.atguigu.gmall.order.service.OrderService;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.rabbitmq.client.Channel;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @author Fxz
 * @version 1.0
 * @date 2022-02-21 9:44
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class OrderReceiver {

	private final OrderService orderService;

	private final PaymentFeignClient paymentFeignClient;

	/**
	 * 监听延时消息 取消订单
	 */
	@SneakyThrows
	@RabbitListener(queues = { MqConst.QUEUE_ORDER_CANCEL })
	public void orderCancel(Long id, Message message, Channel channel) {
		long tag = message.getMessageProperties().getDeliveryTag();
		channel.basicAck(tag, false);
		log.info("延时消息:{}", id);
		// 取消订单的业务逻辑
		if (id != null) {
			OrderInfo orderInfo = orderService.getById(id);
			// 判断订单状态和进度状态
			if (ObjectUtils.isNotEmpty(orderInfo) && "UNPAID".equals(orderInfo.getOrderStatus())
					&& "UNPAID".equals(orderInfo.getProcessStatus())) {
				// 是否存在电商交易记录
				PaymentInfo paymentInfo = paymentFeignClient.getPaymentInfo(orderInfo.getOutTradeNo());
				if (ObjectUtils.isNotEmpty(paymentInfo) && "UNPAID".equals(paymentInfo.getPaymentStatus())) {
					Boolean checkPayment = paymentFeignClient.checkPayment(orderInfo.getId());
					if (checkPayment) {
						// 关闭订单、本地电商记录、支付宝电商记录
						Boolean flag = paymentFeignClient.closePay(orderInfo.getId());
						if (flag) {
							// 关闭订单、本地电商记录
							orderService.execExpiredOrder(id, "2");
						}
					}
					else {
						// 关闭订单、本地电商记录
						orderService.execExpiredOrder(id, "2");
					}
				}
				else {
					// 只关闭订单
					orderService.execExpiredOrder(id, "1");
				}
			}
		}
	}

	/**
	 * 监听订单消息
	 */
	@SneakyThrows
	@RabbitListener(bindings = @QueueBinding(
			value = @Queue(value = MqConst.QUEUE_PAYMENT_PAY, durable = "true", autoDelete = "false"),
			exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_PAYMENT_PAY), key = { MqConst.ROUTING_PAYMENT_PAY }))
	public void paymentPay(Long orderId, Message message, Channel channel) {
		log.info("监听更新订单状态的消息:{}", orderId);
		if (orderId != null) {
			OrderInfo orderInfo = orderService.getOrderInfo(orderId);
			if (ObjectUtils.isNotEmpty(orderInfo) && "UNPAID".equals(orderInfo.getOrderStatus())
					&& "UNPAID".equals(orderInfo.getProcessStatus())) {
				// 更新订单状态
				orderService.updateOrderStatus(orderId, ProcessStatus.PAID);
				// 发消息给库存 减少库存
				orderService.sendOrderStatus(orderId);
			}
		}
		channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
	}

	/**
	 * 监听库存系统发送的减库存结果
	 */
	@SneakyThrows
	@RabbitListener(bindings = @QueueBinding(
			value = @Queue(value = MqConst.QUEUE_WARE_ORDER, durable = "true", autoDelete = "false"),
			exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_WARE_ORDER), key = { MqConst.ROUTING_WARE_ORDER }))
	public void updateOrderStatus(String wareJson, Message message, Channel channel) {
		if (StringUtils.isNotBlank(wareJson)) {
			// wareJson转map
			Map map = JSON.parseObject(wareJson, Map.class);
			String orderId = (String) map.get("orderId");
			String status = (String) map.get("status");
			if ("DEDUCTED".equals(status)) {
				// 减库存成功 更新状态
				orderService.updateOrderStatus(Long.valueOf(orderId), ProcessStatus.WAITING_DELEVER);
			}
			else {
				// 异常情况
				orderService.updateOrderStatus(Long.valueOf(orderId), ProcessStatus.STOCK_EXCEPTION);
			}
		}
		channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
	}

}
